package World;



import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.Random;

import javax.swing.ImageIcon;
import javax.swing.JOptionPane;

public class FractalNoise {

	public static Random random = new Random();

	public int w, h;
	public double[][] map;

	public FractalNoise(int w, int h, int featureSize) {
		map = new double[w][h];
		this.w = w;
		this.h = h;
		map = new double[w][h];
		int stepSize = featureSize;
		double scale = 1.0 / w;
		double scaleMod = 1;
		for (int y = 0; y < h; y += stepSize) {
			for (int x = 0; x < w; x += stepSize) {
				setSample(x, y, random.nextFloat() * 2 - 1);
			}
		}
		while (stepSize > 1) {
			int halfStep = stepSize / 2;
			for (int y = 0; y < w; y += stepSize) {
				for (int x = 0; x < w; x += stepSize) {
					double a = sample(x, y);
					double b = sample(x + stepSize, y);
					double c = sample(x, y + stepSize);
					double d = sample(x + stepSize, y + stepSize);

					double e = (a + b + c + d) / 4.0 + (random.nextFloat() * 2 - 1) * stepSize * scale;
					setSample(x + halfStep, y + halfStep, e);
				}
			}
			for (int y = 0; y < w; y += stepSize) {
				for (int x = 0; x < w; x += stepSize) {
					double a = sample(x, y);
					double b = sample(x + stepSize, y);
					double c = sample(x, y + stepSize);
					double d = sample(x + halfStep, y + halfStep);
					double e = sample(x + halfStep, y - halfStep);
					double f = sample(x - halfStep, y + halfStep);

					double H = (a + b + d + e) / 4.0 + (random.nextFloat() * 2 - 1) * stepSize * scale;
					double g = (a + c + d + f) / 4.0 + (random.nextFloat() * 2 - 1) * stepSize * scale;
					setSample(x + halfStep, y, H);
					setSample(x, y + halfStep, g);
				}
			}
			stepSize /= 2.0;
			scale *= 1.2;
		}
	}

	public double sample(int x, int y) {
		return map[x & (w - 1)][y & (h - 1)];
	}

	public void setSample(int x, int y, double value) {
		map[x & (w - 1)][y & (h - 1)] = value;
	}

	
	public static void main(String[] args){
		int width = 256;
		int height = 256;
		FractalNoise noise = new FractalNoise(width,height, 64);
		BufferedImage image = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);
		int[] rgbs = new int[width * height];
		for(int y = 0; y < height; y++)
			for(int x = 0; x < width; x++){
				int i = x + y * width;
				int col = (int)(noise.map[x][y] * 255 +  128);
				rgbs[i] = col << 16 | col << 8 | col;
			}
		image.setRGB(0, 0, width, height, rgbs, 0, width);
		
		JOptionPane.showMessageDialog(null, null, "Random noise", JOptionPane.YES_NO_CANCEL_OPTION, new ImageIcon(image.getScaledInstance(width * 2, height * 2, Image.SCALE_AREA_AVERAGING)));
	}
}
